﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;

namespace SportManager
{
    public partial class StatisticDlg : Form
    {
        private const double Factor = 0.025;
        private string m_Parameter;

        public StatisticDlg(string parameter = "")
        {
            InitializeComponent();
            m_Parameter = parameter;
            List<Training> list = Program.TrainingsKeeper.GetData();
            list.Sort(Training.CompareByDate);
        }

        private void FillAntopometricParameters(List<AntropometricalData> data, string parameter = "")
        {
            int selectedIndex = 0;
            int i = 0;
            foreach (string key in data[0].Items.Keys)
            {
                comboBox1.Items.Add(data[0].Items[key]);
                if (parameter.Length != 0 && key == parameter)
                {
                    selectedIndex = i;
                }

                i++;
            }

            comboBox1.SelectedIndex = selectedIndex;
        }        

        private string FindKeyByPropertyName(List<AntropometricalData> data, string name)
        {
            foreach (string key in data[0].Items.Keys)
            {
                if (data[0].Items[key].Name == name)
                {
                    return key;
                }
            }

            throw new Exception("Wrong key");
        }

        private void FillAntropGraphForSelectedParameter(List<AntropometricalData> data)
        {
            string targetKet = FindKeyByPropertyName(data, comboBox1.SelectedItem.ToString());
            double min = double.MaxValue;
            double max = double.MinValue;

            chart1.Series["Series1"].Points.Clear();
            foreach (AntropometricalData item in data)
            {
                double? value = item.Items[targetKet].Value;
                if (value == null)
                {
                    continue;
                }

                chart1.Series["Series1"].Points.AddXY(item.Date, value);
                if (value > max)
                {
                    max = value.Value;
                }

                if (value < min)
                {
                    min = value.Value;
                }
            }
            
            chart1.ChartAreas[0].AxisY.Maximum = System.Math.Round(max + max * Factor, MidpointRounding.AwayFromZero);
            chart1.ChartAreas[0].AxisY.Minimum = System.Math.Round(min - min * Factor, MidpointRounding.AwayFromZero);
            chart1.ChartAreas[0].AxisY.Interval = CalculateInterval((chart1.ChartAreas[0].AxisY.Maximum - chart1.ChartAreas[0].AxisY.Minimum));
        }

        private double CalculateInterval(double delta)
        {
            if (delta < 1) return 0.1;
            if (delta < 5) return 0.5;
            if (delta < 10) return 1.0;
            if (delta < 50) return 5;

            return (Math.Round(delta / 10));
        }

        private void FillExercisesList(List<ExerciseInfo> data)
        {
            foreach (ExerciseInfo item in data)
            {
                comboBox2.Items.Add(item);
            }

            comboBox2.SelectedIndex = 0;
        }

        private void FillExercisesWeightGraphForSelected()
        {
            List<Training> data = Program.TrainingsKeeper.GetData();
            chart3.Series["Series1"].Points.Clear();
            Dictionary<Double, int> dict = new Dictionary<double, int>();
            foreach (Training training in data)
            {
                foreach (Exercise exercise in training.Exercises)
                {
                    if (exercise.Id != ((ExerciseInfo)comboBox2.SelectedItem).Id)
                    {
                        continue;
                    }

                    foreach (Approach approach in exercise.Approachs)
                    {
                        if (!dict.ContainsKey(approach.Weight))
                        {
                            dict.Add(approach.Weight, approach.Repeats);
                        }

                        if (dict[approach.Weight] < approach.Repeats)
                        {
                            dict[approach.Weight] = approach.Repeats;
                        }
                    }
                }
            }
            
            foreach (double key in dict.Keys)
            {
                chart3.Series["Series1"].Points.AddXY(key, dict[key]);
            }

            chart3.Series["Series1"].ChartType = SeriesChartType.Point;
        }

        private void FillExercisesRepeatsGraphForSelected()
        {
            List<Training> data = Program.TrainingsKeeper.GetData();
            chart2.Series["Series1"].Points.Clear();
            double min = double.MaxValue;
            double max = double.MinValue;

            foreach (Training training in data)
            {
                foreach (Exercise exercise in training.Exercises)
                {
                    double maxWeight = 0;
                    foreach (Approach approach in exercise.Approachs)
                    {
                        if (approach.Weight > maxWeight)
                        {
                            maxWeight = approach.Weight;
                        }
                    }                    

                    if (exercise.Id == ((ExerciseInfo)comboBox2.SelectedItem).Id && maxWeight != 0)
                    {
                        if (maxWeight < min)
                        {
                            min = maxWeight;
                        }

                        if (maxWeight > max)
                        {
                            max = maxWeight;
                        }

                        chart2.Series["Series1"].Points.AddXY(training.StartDate, maxWeight);
                    }
                }
            }
            
            chart2.ChartAreas[0].AxisY.Minimum = Math.Round((min - min * Factor), MidpointRounding.ToEven);
            chart2.ChartAreas[0].AxisY.Maximum = Math.Round((max + max * Factor), MidpointRounding.ToEven);
            chart2.ChartAreas[0].AxisY.Interval = CalculateInterval((chart2.ChartAreas[0].AxisY.Maximum - chart2.ChartAreas[0].AxisY.Minimum) * 2);
        }

        private void StatisticDlg_Load(object sender, EventArgs e)
        {
            dialogHeader1.SetHeaderText("Статистика выполненных упражнений и антропометрических параметров");
            dialogHeader1.SetDescriptionText("Выберете интересующий вас параметр для просмотра статистики");
            dialogHeader1.SetIcon(Resource.pie_chart_icon32);

            List<AntropometricalData> antropometricData = Program.AntropometricKeeper.GetData();
            antropometricData.Sort(AntropometricalData.CompareByDate);

            if (antropometricData.Count != 0)
            {
                FillAntopometricParameters(antropometricData, m_Parameter);
                FillAntropGraphForSelectedParameter(antropometricData);
            }

            List<ExerciseInfo> exercisesData = Program.ExercisesKeeper.GetData();
            if (exercisesData.Count != 0)
            {
                FillExercisesList(exercisesData);
                FillExercisesWeightGraphForSelected();
                FillExercisesRepeatsGraphForSelected();
            }
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            FillAntropGraphForSelectedParameter(Program.AntropometricKeeper.GetData());
        }

        private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
        {
            FillExercisesWeightGraphForSelected();
            FillExercisesRepeatsGraphForSelected();
        }
    }
}
